#include <QMessageBox>
#include <QToolTip>
#include <QPalette>
#include <QFont>
#include <QSettings>
#include <QTextCodec>
#include <synchapi.h>
#include <QDebug>
#include <QDateTime>
#include <QTimer>

#include "qlsloginappfwk.h"
#include "ui_qlsloginappfwk.h"
#include "../../DevBase/dllQLsDBManager/qlsdbconnpool.h"

/* static */
QCache<QString, User> QLsLoginAppfwk::userCache;

QLsLoginAppfwk::QLsLoginAppfwk(QWidget *parent) :
	QWidget(parent),
	ui(new Ui::QLsLoginAppfwk)
{
	/* 注册事件过滤器 */
	installEventFilter(this);

	/* 是否需要登录功能 */
	QSettings settings("ini/login.ini", QSettings::IniFormat);
	settings.setIniCodec(QTextCodec::codecForName("utf-8"));
	enable = settings.value("login/enable", false).toBool();
	if(!enable) return;

	/* 数据库初始化 */
	DataBaseInit();

	ui->setupUi(this);

	/* 主界面初始化 */
	homeInit();

	/* 读取本地缓存 */
	readLocalCache();

	/* 切换到登录主界面 */
	ui->stackedWidget->setCurrentIndex(0);
}

QLsLoginAppfwk::~QLsLoginAppfwk()
{
	delete ui;
}

/* 登录 */
void QLsLoginAppfwk::on_loginBtn_clicked()
{
	/* 获取用户名和密码内容 */
	QString username = ui->userNameLineEdit->text();
	QString password = ui->pwdLineEdit->text();

	/* 有效性判断 */
	if(username.isEmpty())
	{
		ui->userNameLineEdit->setFocus();
		QToolTip::showText(ui->userNameLineEdit->mapToGlobal(QPoint(0, 0)), "请您输入账号后再登录", this);
		return;
	}
	if(password.isEmpty())
	{
		ui->pwdLineEdit->setFocus();
		QToolTip::showText(ui->pwdLineEdit->mapToGlobal(QPoint(0, 0)), "请您输入密码后再登录", this);
		return;
	}

	/* 用户登录 */
	ui->loginBtn->setText("取    消");
	/* 延时2s，模拟QQ登录，等待用户是否取消登录 */
	//	QThread::sleep(2);
	/* 发送登录验证 */
	User *user = us.findUserByUsernameAndPassword(username, password);
	/* 查无此人 */
	if(!user)
	{
		ui->loginBtn->setText("登    录");
		QMessageBox::critical(this, "错误：", "账号或密码输入错误", QMessageBox::Ok);
		return;
	}

	/* 登录成功，切换到聊天窗口 */
	/* 加入本地缓存 */
	QSettings settings("cache/userCache.ini", QSettings::IniFormat);
	settings.setIniCodec(QTextCodec::codecForName("utf-8"));

	settings.beginGroup("login");
	settings.setValue(QString("0/id"), user->getId());

	settings.beginGroup(QString::number(user->getId()));
	settings.setValue(QString("username"), user->getUsername());
	settings.setValue(QString("password"), user->getPassword());
	settings.setValue(QString("mobile"), user->getMobile());
	settings.setValue(QString("remember"), ui->remeberCheckBox->isChecked());
	settings.setValue(QString("autoLogin"), ui->autoLoginCheckBox->isChecked());
	settings.endGroup();

	settings.endGroup();
	/* 切换到主系统界面 */
	emit sigLogin(*user);
	this->close();
}

/* 切换到注册账号界面 */
void QLsLoginAppfwk::on_toRegisterBtn_clicked()
{
	ui->stackedWidget->setCurrentIndex(1);
}

/* 切换到修改密码界面 */
void QLsLoginAppfwk::on_toAlterBtn_clicked()
{
	ui->stackedWidget->setCurrentIndex(2);
}

/* 切换到找回密码界面 */
void QLsLoginAppfwk::on_toFindBtn_clicked()
{
	ui->stackedWidget->setCurrentIndex(3);
}

/* 返回登录主界面 */
void QLsLoginAppfwk::returnLoginBtn()
{
	ui->stackedWidget->setCurrentIndex(0);
}

/* 注册用户 */
void QLsLoginAppfwk::on_registerBtn_clicked()
{
	/* 获取用户输入内容 */
	QString username = ui->registerUsernamelineEdit->text();
	QString password = ui->registerPwdlineEdit->text();
	QString password2 = ui->registerPwd2lineEdit->text();
	QString mobile = ui->registerMobileLineEdit->text();

	/* 有效性判断 */
	if(username.isEmpty())
	{
		ui->registerUsernamelineEdit->setFocus();
		QToolTip::showText(ui->registerUsernamelineEdit->mapToGlobal(QPoint(0, 0)), "请您输入账号后再注册", this);
		return;
	}
	if(password.isEmpty())
	{
		ui->registerPwdlineEdit->setFocus();
		QToolTip::showText(ui->registerPwdlineEdit->mapToGlobal(QPoint(0, 0)), "请您输入密码后再注册", this);
		return;
	}
	if(password2.isEmpty())
	{
		ui->registerPwd2lineEdit->setFocus();
		QToolTip::showText(ui->registerPwd2lineEdit->mapToGlobal(QPoint(0, 0)), "请您输入确认密码后再注册", this);
		return;
	}
	if(mobile.isEmpty())
	{
		ui->registerMobileLineEdit->setFocus();
		QToolTip::showText(ui->registerMobileLineEdit->mapToGlobal(QPoint(0, 0)), "请您输入手机号后再注册", this);
		return;
	}
	if(password != password2)
	{
		ui->registerPwd2lineEdit->clear();
		ui->registerPwd2lineEdit->setFocus();
		QToolTip::showText(ui->registerPwd2lineEdit->mapToGlobal(QPoint(0, 0)), "确认密码不一致", this);
		return;
	}

	/* 开始注册 */
	User user;
	user.setUsername(username);
	user.setPassword(password);
	user.setMobile(mobile);
	user.setDate(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
	switch(us.addUser(user))
	{
	case UserService::UserType::ERRNO_SUCCESS:				/* 注册成功 */
		QMessageBox::information(this, "提示：", "注册成功", QMessageBox::Ok);
		/* 返回登录主界面 */
		ui->stackedWidget->setCurrentIndex(0);
		break;
	case UserService::UserType::ERRNO_ALREADYEXIST:			/* 该账号已存在 */
		QMessageBox::critical(this, "错误：", "该账号已存在", QMessageBox::Ok);
		break;
	case UserService::UserType::ERRNO_MOBILE_ALREADYEXIST:	/* 该手机号已绑定 */
		QMessageBox::critical(this, "错误：", "该手机号已绑定", QMessageBox::Ok);
		break;
	default:
		break;
	}
}

/* 修改密码 */
void QLsLoginAppfwk::on_alterBtn_clicked()
{
	/* 获取用户输入内容 */
	QString username = ui->alterUsernamelineEdit->text();
	QString oldPwd = ui->alterOldPwdlineEdit->text();
	QString mobile = ui->alterMobileLineEdit->text();
	QString newPwd = ui->alterNewPwdlineEdit->text();
	QString newPwd2 = ui->alterNewPwd2lineEdit->text();

	/* 有效性判断 */
	if(username.isEmpty())
	{
		ui->alterUsernamelineEdit->setFocus();
		QToolTip::showText(ui->alterUsernamelineEdit->mapToGlobal(QPoint(0, 0)), "请您输入账号后再修改", this);
		return;
	}
	if(oldPwd.isEmpty())
	{
		ui->alterOldPwdlineEdit->setFocus();
		QToolTip::showText(ui->alterOldPwdlineEdit->mapToGlobal(QPoint(0, 0)), "请您输入旧密码后再修改", this);
		return;
	}
	if(mobile.isEmpty())
	{
		ui->alterMobileLineEdit->setFocus();
		QToolTip::showText(ui->alterMobileLineEdit->mapToGlobal(QPoint(0, 0)), "请您输入手机号后再修改", this);
		return;
	}
	if(newPwd.isEmpty())
	{
		ui->alterNewPwdlineEdit->setFocus();
		QToolTip::showText(ui->alterNewPwdlineEdit->mapToGlobal(QPoint(0, 0)), "请您输入新密码后再修改", this);
		return;
	}
	if(newPwd2.isEmpty())
	{
		ui->alterNewPwd2lineEdit->setFocus();
		QToolTip::showText(ui->alterNewPwd2lineEdit->mapToGlobal(QPoint(0, 0)), "请您输入确认密码后再修改", this);
		return;
	}
	if(newPwd != newPwd2)
	{
		ui->alterNewPwd2lineEdit->clear();
		ui->alterNewPwd2lineEdit->setFocus();
		QToolTip::showText(ui->alterNewPwd2lineEdit->mapToGlobal(QPoint(0, 0)), "确认密码不一致", this);
		return;
	}

	/* 用户验证 */
	User *user = us.findUserByUsernameAndPwdAndMobile(username, oldPwd, mobile);
	/* 查无此人 */
	if(!user)
	{
		QMessageBox::critical(this, "错误：", "信息输入错误", QMessageBox::Ok);
		return;
	}

	/** INFO:上面find到的在userCache缓存中，会被下面的updateUser方法清空，导致后续访问该空间会崩溃 */
	user = new User(*user);

	/* 修改密码 */
	user->setPassword(newPwd);
	switch(us.updateUser(*user))
	{
	case UserService::UserType::ERRNO_SUCCESS:		/* 修改完成 */
		QMessageBox::information(this, "提示：", "修改成功", QMessageBox::Ok);
		/* 返回登录主界面 */
		ui->stackedWidget->setCurrentIndex(0);
		break;
	case UserService::UserType::ERRNO_INEXISTENCE:	/* 信息错误 */
		QMessageBox::critical(this, "错误：", "信息输入错误", QMessageBox::Ok);
		delete user;
		return;
		break;
	default:
		break;
	}

	/* 修改密码后，清除上次本地缓存：密码、记住密码、自动登录，清空 */
	QSettings settings("cache/userCache.ini", QSettings::IniFormat);
	settings.setIniCodec(QTextCodec::codecForName("utf-8"));
	settings.beginGroup("login");
	settings.beginGroup(QString::number(user->getId()));
	settings.setValue(QString("username"), user->getUsername());
	settings.setValue(QString("password"), "");
	settings.setValue(QString("mobile"), user->getMobile());
	settings.setValue(QString("remember"), false);
	settings.setValue(QString("autoLogin"), false);
	settings.endGroup();
	settings.endGroup();
	delete user;
}

/* 找回密码 */
void QLsLoginAppfwk::on_findBtn_clicked()
{
	/* 获取用户输入内容 */
	QString username = ui->findUsernameLineEdit->text();
	QString mobile = ui->findMobileLineEdit->text();
	QString newPwd = ui->findNewPwdLineEdit->text();
	QString newPwd2 = ui->findNewPwd2LineEdit->text();

	/* 有效性判断 */
	if(username.isEmpty())
	{
		ui->findUsernameLineEdit->setFocus();
		QToolTip::showText(ui->findUsernameLineEdit->mapToGlobal(QPoint(0, 0)), "请您输入账号后再找回", this);
		return;
	}
	if(mobile.isEmpty())
	{
		ui->findMobileLineEdit->setFocus();
		QToolTip::showText(ui->findMobileLineEdit->mapToGlobal(QPoint(0, 0)), "请您输入手机号后再找回", this);
		return;
	}
	if(newPwd.isEmpty())
	{
		ui->findNewPwdLineEdit->setFocus();
		QToolTip::showText(ui->findNewPwdLineEdit->mapToGlobal(QPoint(0, 0)), "请您输入新密码后再找回", this);
		return;
	}
	if(newPwd2.isEmpty())
	{
		ui->findNewPwd2LineEdit->setFocus();
		QToolTip::showText(ui->findNewPwd2LineEdit->mapToGlobal(QPoint(0, 0)), "请您输入确认密码后再找回", this);
		return;
	}
	if(newPwd != newPwd2)
	{
		ui->findNewPwd2LineEdit->clear();
		ui->findNewPwd2LineEdit->setFocus();
		QToolTip::showText(ui->findNewPwd2LineEdit->mapToGlobal(QPoint(0, 0)), "确认密码不一致", this);
		return;
	}

	/* 用户验证 */
	User *user = us.findUserByUsernameAndMobile(username, mobile);
	/* 查无此人 */
	if(!user)
	{
		QMessageBox::critical(this, "错误：", "信息输入错误", QMessageBox::Ok);
		return;
	}

	/** INFO:上面find到的在userCache缓存中，会被下面的updateUser方法清空，导致后续访问该空间会崩溃 */
	user = new User(*user);

	/* 找回密码 */
	user->setPassword(newPwd);
	switch(us.updateUser(*user))
	{
	case UserService::UserType::ERRNO_SUCCESS:			/* 找回完成 */
		QMessageBox::information(this, "提示：", "找回成功", QMessageBox::Ok);
		/* 返回登录主界面 */
		ui->stackedWidget->setCurrentIndex(0);
		break;
	case UserService::UserType::ERRNO_INEXISTENCE:		/* 信息错误 */
		QMessageBox::critical(this, "错误：", "信息输入错误", QMessageBox::Ok);
		delete user;
		return;
		break;
	default:
		break;
	}

	/* 找回密码后，清除上次本地缓存：密码、记住密码、自动登录，清空 */
	QSettings settings("cache/userCache.ini", QSettings::IniFormat);
	settings.setIniCodec(QTextCodec::codecForName("utf-8"));
	settings.beginGroup("login");
	settings.beginGroup(QString::number(user->getId()));
	settings.setValue(QString("username"), user->getUsername());
	settings.setValue(QString("password"), "");
	settings.setValue(QString("mobile"), user->getMobile());
	settings.setValue(QString("remember"), false);
	settings.setValue(QString("autoLogin"), false);
	settings.endGroup();
	settings.endGroup();
	delete user;
}

/* 鼠标事件重载 - 按下事件 */
void QLsLoginAppfwk::mousePressEvent(QMouseEvent *event)
{
	bPressFlag = true;
	beginDrag = event->pos();
	QWidget::mousePressEvent(event);
}

/* 鼠标事件重载 - 释放事件 */
void QLsLoginAppfwk::mouseReleaseEvent(QMouseEvent *event)
{
	bPressFlag = false;
	QWidget::mouseReleaseEvent(event);
}

/* 鼠标事件重载 - 移动事件 */
void QLsLoginAppfwk::mouseMoveEvent(QMouseEvent *event)
{
	if(bPressFlag)
	{
		QPoint relaPos(QCursor::pos() - beginDrag);
		move(relaPos);
	}
	QWidget::mouseMoveEvent(event);
}

/* 事件过滤器 */
bool QLsLoginAppfwk::eventFilter(QObject *target, QEvent *event)
{
	if(event->type() == QEvent::ShowToParent)
	{
		if(!enable)
		{	/* 不要登录界面，开始就关闭，并发送登录信号 */
			emit sigLogin(User());
			close();
			return true;
		}
	}

	return QWidget::eventFilter(target, event);
}

/* 记住密码 */
void QLsLoginAppfwk::on_remeberCheckBox_stateChanged(int arg1)
{
	/* 取消记住密码，同时取消自动登录 */
	if(arg1 == Qt::Unchecked)
	{
		if(ui->autoLoginCheckBox->isChecked())
			ui->autoLoginCheckBox->setChecked(false);
	}
}

/* 自动登录 */
void QLsLoginAppfwk::on_autoLoginCheckBox_stateChanged(int arg1)
{
	/* 自动登录，同时选择记住密码 */
	if(arg1 == Qt::Checked)
	{
		if(!ui->remeberCheckBox->isChecked())
			ui->remeberCheckBox->setChecked(true);
	}
}

/* 输入用户名，自动提示本地已有数据 */
void QLsLoginAppfwk::on_userNameLineEdit_textChanged(const QString &arg1)
{
	/* 获取缓存key列表 */
	QStringList keyList = userCache.keys();
	User *user;
	bool isEmpty = true;

	/* 先清除已经存在的数据，不然的话每次文本变更都会插入数据，最后出现重复数据 */
	userModel->removeRows(0, userModel->rowCount());

	/* 检索数据 */
	foreach(QString key, keyList)
	{
		user = userCache.object(key);
		if(arg1 != "" && QString(user->getUsername().data()).indexOf(arg1) == 0)
		{	/* 如果有，自动填写 */
			userModel->insertRow(0);
			userModel->setData(userModel->index(0, 0),
							   user->getUsername());
			ui->pwdLineEdit->setText(user->getPassword());
			isEmpty = false;
		}
	}

	/* 如果没有响应数据，密码清空 */
	if(isEmpty)
		ui->pwdLineEdit->clear();
}

/* 用户名自动提示：选择 */
void QLsLoginAppfwk::onUserChoosed(const QString &key)
{
	User *user = userCache.object(key);
	ui->userNameLineEdit->setText(user->getUsername());
	ui->pwdLineEdit->setText(user->getPassword());
}

/* 主界面初始化 */
void QLsLoginAppfwk::homeInit()
{
	/* 主窗口 */
	setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
	setAttribute(Qt::WA_TranslucentBackground);                     //隐藏窗口，只显示控件
	setFixedSize(this->size());                                     //禁止拖动窗口大小

	/* 用户名输入框自动提示 */
	userModel = new QStandardItemModel(0, 1, ui->userNameLineEdit);
	userCompleter = new QCompleter(userModel, ui->userNameLineEdit);
	userCompleter->setCompletionMode(QCompleter::InlineCompletion);
	ui->userNameLineEdit->setCompleter(userCompleter);
	connect(userCompleter, SIGNAL(activated(const QString&)), this, SLOT(onUserChoosed(const QString&)));

	/* 连接 */
	connect(ui->registerReturnLoginBtn, SIGNAL(clicked()), this, SLOT(returnLoginBtn()));
	connect(ui->alterReturnLoginBtn, SIGNAL(clicked()), this, SLOT(returnLoginBtn()));
	connect(ui->findReturnLoginBtn, SIGNAL(clicked()), this, SLOT(returnLoginBtn()));
}

/* 读取本地缓存 */
void QLsLoginAppfwk::readLocalCache()
{
	quint32 id = 0;
	User *user;
	QStringList idStrList;
	QStringList keyList;
	QSettings settings("cache/userCache.ini", QSettings::IniFormat);
	bool isRem = false, isAuto = false;
	QString loginIdStr;

	/* 获取login下的所有用户 */
	settings.setIniCodec(QTextCodec::codecForName("utf-8"));
	settings.beginGroup("login");
	idStrList = settings.childGroups();

	/* 遍历每个用户的数据 */
	foreach(QString idStr, idStrList)
	{
		settings.beginGroup(idStr);
		keyList = settings.childKeys();

		/* 遍历该用户的所有数据 */
		foreach(QString key, keyList)
		{
			QString value = settings.value(key).toString();

			/* 上次登录id记录 */
			if(idStr == "0")
				id = value.toUInt();
			/* 其余记录所有用户信息 */
			else
			{	/* 如果已缓存过该用户，则提取该缓存进行修改 */
				if(userCache.contains(idStr))
					user = userCache.object(idStr);
				/* 否则，新建用户并缓存 */
				else user = new User;

				user->setId(idStr.toUInt());
				if(key == "username")
					user->setUsername(value);
				else if(key == "password")
					user->setPassword(value);
				else if(key == "mobile")
					user->setMobile(value);
				else if(key == "remember" && user->getId() == id && value == "true")
				{	/* 记住密码 */
					loginIdStr = idStr;
					isRem = true;
				}
				else if(key == "autoLogin" && value == "true")
				{	/* 自动登录 */
					isAuto = true;
				}

				/* 更新缓存 */
				if(!userCache.contains(idStr))
					userCache.insert(idStr, user);
			}
		}
		settings.endGroup();
	}
	settings.endGroup();

	/* 判断是否有 记住密码/自动登录 */
	user = userCache.object(loginIdStr);
	if(isRem)
	{
		ui->userNameLineEdit->setText(user->getUsername());
		ui->pwdLineEdit->setText(user->getPassword());
		ui->remeberCheckBox->setChecked(true);
	}
	if(isAuto)
	{
		ui->autoLoginCheckBox->setChecked(true);
		QTimer::singleShot(1, this, &QLsLoginAppfwk::on_loginBtn_clicked);
	}
}

/* 数据库初始化 */
void QLsLoginAppfwk::DataBaseInit()
{
	/* 数据库校验 */

	/* 用户表 */
	if(!us.exists(QLsDBConnPool::getType()))
	{
		/* 校验失败，创建一个 */
		us.CreateTable(QLsDBConnPool::getType());

		/* 创建完，确认一下 */
		if(!us.exists(QLsDBConnPool::getType()))
		{
			QMessageBox::critical(this, "提示", "数据库初始化失败！");
			QTimer::singleShot(0, qApp, &QApplication::quit);
			return;
		}
	}
}
